#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

const std::string gpath = "/home/ybt/linux-learning-journey/lesson12/2.sharemem";
int gprojId = 0x6666;
size_t gshmsize = 4096;
mode_t gshmmode = 0600;

std::string ToHex(key_t key)
{
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "0x%X", key);
    return std::string(buffer);
}

class ShareMemory
{
public:
    ShareMemory():_shmid(-1), _key(0), _p(nullptr)
    {
    }
    ~ShareMemory()
    {
    }
    void CreateShm()
    {
        if (_shmid != -1)
        {
            return;
        }
        CreateShmHelper(IPC_CREAT | IPC_EXCL | gshmmode);
    }
    void GetShm()
    {
        CreateShmHelper(IPC_CREAT | gshmmode);
    }
    void AttachShm()
    {
        _p = ::shmat(_shmid, nullptr, 0);
        if ((long long)_p == -1)
        {
            std::cerr << "shmat error" << std::endl;
        }
    }
    void DetachShm()
    {
        if (_p == nullptr)
        {
            return;
        }
        ::shmdt(_p);
    }
    void DeleteShm()
    {
        int ret = ::shmctl(_shmid, IPC_RMID, nullptr);
        if (ret < 0)
        {
            std::cerr << "shmctl error" << std::endl;
            return;
        }
    }
    void* GetAddr()
    {
        return _p;
    }
    void ShmMeta()
    {
    }

private:
    void CreateShmHelper(int shmflg)
    {
        // 1. 创建key
        _key = ::ftok(gpath.c_str(), gprojId);
        if (_key < 0)
        {
            std::cerr << "ftok error" << std::endl;
        }
        // 2. 创建共享内存
        _shmid = ::shmget(_key, gshmsize, shmflg);
        if (_shmid < 0)
        {
            std::cerr << "shmget error" << std::endl;
        }
    }

private:
    int _shmid;
    key_t _key;
    void *_p;
};

ShareMemory gShareMemory;

struct data
{
    char status[32];
    char lsttime[48];
    char image[4000];
};